package com.huwaiwai001.arraylist;

import java.util.ArrayList;
import java.util.Arrays;

/**
 * 简单实现的 表数据结构
 * 参考 ArrayList 使用数组存储 支持泛型
 * Created by hww on 2018/9/24 下午10:29.
 */
public class MyArrayList<T> {

    /** 初始化时的大小 */
    private static final int DEFAULT_SIZE = 16;
    /** 最大容量 */
    private static final int MAX_SIZE = Integer.MAX_VALUE;

    /** 列表容量 */
    private int size;
    /** 列表元素计数 */
    private int count;
    /** 实际存放元素的容器 */
    private Object [] elements;

    /** 默认构造一个初始化容量为16的容器 */
    public MyArrayList() {
        this(DEFAULT_SIZE);
    }

    /** 可以指定初始化大小的构造方法 */
    public MyArrayList(int size) {
        if (size < 0) {
            //允许创建大小为0的表
            throw new IllegalArgumentException("初始化大小不能小于0");
        }
        this.size = size;
        this.elements = new Object[size];
        this.count = 0;
    }

    //todo 其他构造方法
    // 比如可以传入一个数组、列表 进行初始化
    // 比如可以传入自定义个元素个数 进行初始化


    /** 添加一个元素 */
    public void add(T element) {
        if (count == size) {
            //当队列中的元素 已经达到最大容量时 进行扩容操作
            //若扩容失败 会抛出OOM异常
            resize();
        }
        this.elements[count++] = element;
    }

    /** 获取一个元素 */
    public T get(int index) {
        if (index + 1 > count) {
            throw new ArrayIndexOutOfBoundsException();
        }
        return (T) elements[index];
    }

    public int size() {
        return count;
    }

    public int length() {
        return size;
    }

    /** 扩容操作 */
    private void resize() {
        if (size == MAX_SIZE) {
            //如果已经达到最大值了 无法再扩容
            throw new OutOfMemoryError("列表已达最大容量 无法扩容");
        }
        int oldSize = size;
        //新大小为原来的1.5倍
        int newSize = oldSize + (oldSize >> 1);

        if (newSize < 0) {
            //若1.5倍会溢出 则设置为最大值
            size = MAX_SIZE;
        } else {
            size = newSize;
        }
        elements = Arrays.copyOf(elements, size);
    }

}
